#include "mousetrackingworker.h"
#include <QDebug>
#include <QTimer>
#include <cmath>
#include <QSocketNotifier>
#include <QDebug>
#include <fcntl.h>    // For open()
#include <unistd.h>   // For close()
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/input.h>

MouseTrackingWorker::MouseTrackingWorker(QObject *parent)
    : QObject(parent), lastX(0), lastY(0), currentX(0), currentY(0)
{

}

MouseTrackingWorker::~MouseTrackingWorker()
{
    qInfo() << "MouseTrackingWorker::~MouseTrackingWorker()";
    deviceFile.close();
    delete notifier;
}

double MouseTrackingWorker::getMoveDistance()
{
    //QMutexLocker locker(&mutex);  // 保证线程安全
    double out = std::sqrt(lastX * lastX + lastY * lastY);
    lastX = 0;
    lastY = 0;
    qInfo() << "[SRC] getMoveDistanceAct " <<out;
    return out;
}


void MouseTrackingWorker::init(const QString &devicePath)
{
    // 打开设备文件，返回文件描述符
    deviceFd = open(devicePath.toUtf8().constData(), O_RDONLY);

    if (deviceFd < 0) {
        qWarning() << "Failed to open device:" << devicePath << "Error:" << strerror(errno);
        return;
    }

    // 使用QSocketNotifier监听文件描述符的可读事件
    notifier = new QSocketNotifier(deviceFd, QSocketNotifier::Read, this);
    connect(notifier, &QSocketNotifier::activated, this, &MouseTrackingWorker::process);

    qInfo() << "MouseTrackingWorker::init";
    qInfo() << "Device file status: open";
    qInfo() << "Available bytes: checking...";

    // // 创建定时器来定期检查设备文件的可用字节数
    // QTimer *timer = new QTimer(this);
    // connect(timer, &QTimer::timeout, this, [this]() {
    //     // 由于直接操作文件描述符，设备文件没有像QFile一样的方便接口
    //     // 所以这里只是输出一个提示信息
    //     qInfo() << "Checking available bytes...";
    // });
    // timer->start(500);  // 每500ms触发一次
}

// void MouseTrackingWorker::init(const QString &devicePath)
// {
//     deviceFile.setFileName(devicePath);
//     if (!deviceFile.open(QIODevice::ReadOnly)) {
//         qWarning() << "Failed to open device:" << devicePath << "Error:" << deviceFile.errorString();
//         return;
//     }

//     notifier = new QSocketNotifier(deviceFile.handle(), QSocketNotifier::Read, this);
//     connect(notifier, &QSocketNotifier::activated, this, &MouseTrackingWorker::process);
//     qInfo() << "MouseTrackingWorker::init" ;
//     qInfo() << "Device file status: " << deviceFile.isOpen();
//     qInfo() << "Available bytes: " << deviceFile.bytesAvailable();

//     QTimer *timer = new QTimer(this);
//     connect(timer, &QTimer::timeout, this, [this]() {
//         qInfo() << "Available bytes: " << deviceFile.bytesAvailable();
//     });
//     timer->start(100);  // 每100ms触发一次


// }

void MouseTrackingWorker::processMouseData(const struct input_event &event)
{
    // 保存当前的X和Y偏移量
    int delta_x = 0, delta_y = 0;

    // 判断事件类型
    if (event.type == EV_REL) {
        switch (event.code) {
        case REL_X:   // X轴相对移动
            delta_x = event.value;
            break;
        case REL_Y:   // Y轴相对移动
            delta_y = event.value;
            break;
        default:
            break;
        }
    }

    // 如果是相对事件，更新累计的偏移量
    if (delta_x != 0 || delta_y != 0) {
        lastX += delta_x;
        lastY += delta_y;
    }

    // 输出当前的鼠标坐标位置（相对坐标和绝对坐标）
    //qInfo() << "Current Position -> X:" << last_x << ", Y:" << last_y;
}

void MouseTrackingWorker::process()
{
    if (deviceFd < 0) {
        qWarning() << "Device file is not open.";
        return;
    }

    struct input_event in_ev;
    ssize_t bytesRead = read(deviceFd, &in_ev, sizeof(struct input_event));

    if (bytesRead == -1) {
        // 检查是否是“No such device”错误
        if (errno == ENODEV) {
            qWarning() << "Failed to read input event from device. Error: No such device";
            emit deviceDisconnected();  // 发出设备断开信号
            close(deviceFd);  // 关闭文件描述符
            deviceFd = -1;    // 标记设备已关闭
        } else {
            qWarning() << "Failed to read input event from device. Error:" << strerror(errno);
        }
        return;
    }

    if (bytesRead != sizeof(struct input_event)) {
        qWarning() << "Read incomplete data from device.";
        return;
    }

    processMouseData(in_ev);
}

